//////////////////////////////////////////////////////////////////////////////
// Name:        filedlgg.cpp
// Purpose:     wxGenericFileDialog stub to include the source
// Author:      John Labenski, Robert Roebling
// Modified by:
// Created:     12/12/98
// RCS-ID:
// Copyright:   (c) Robert Roebling
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

// MSVC cannot use environment var $(WXWIN)/src/generic/filedlgg.cpp in their
// project files to allow you to compile the generic file dialog.
// You have to specify the relative or absolute path to the wxWidgets
// distribution which is annoying since everyone will probably have it in a
// different place. By #including the source from this file we can avoid this
// and use the $(WXWIN) environment var in the -I include path.

#include "precomp.h"

#include "wx/things/thingdef.h"

#include "wx/defs.h"
#include "wx/filedlg.h"
#include "wx/volume.h"           // wxFSVolumeBase
#include "wx/generic/dirctrlg.h" // wxFileIconsTable
//#include "wx/generic/filedlgg.h"

// If we didn't include the generic filedlgg then include the source here
// NOTE: There may be special cases where more sophisticated tests may be
//       required.

//#ifndef _WX_FILEDLGG_H_
//
//    // Typically we have $(WXWIN)/include in the search path so this should
//    // find the path to filedlgg correctly.
//    #include "../src/generic/filedlgg.cpp"
//
//// --------------------------------------------------------------------------
//// DO NOT DELETE : Cmake will configure this file and replace the marker below.
//// @CMAKE_CONFIGURE_WXTHINGS_FILEDLGG@
//
//
//#endif //_WX_FILEDLGG_H_

// ----------------------------------------------------------------------------
// wxGetAvailableDrives, for WINDOWS, DOS, OS2, MAC, UNIX (returns "/")
// ----------------------------------------------------------------------------

size_t wxGetAvailableDrives(wxArrayString &paths, wxArrayString &names, wxArrayInt &icon_ids)
{
#ifdef wxHAS_FILESYSTEM_VOLUMES

#ifdef __WXWINCE__
    // No logical drives; return "\"
    paths.Add(wxT("\\"));
    names.Add(wxT("\\"));
    icon_ids.Add(wxFileIconsTable::computer);
#elif defined(__WIN32__) && wxUSE_FSVOLUME
    // TODO: this code (using wxFSVolumeBase) should be used for all platforms
    //       but unfortunately wxFSVolumeBase is not implemented everywhere
    const wxArrayString as = wxFSVolumeBase::GetVolumes();

    for (size_t i = 0; i < as.GetCount(); i++)
    {
        wxString path = as[i];
        wxFSVolume vol(path);
        int imageId;
        switch (vol.GetKind())
        {
        case wxFS_VOL_FLOPPY:
            if ( (path == wxT("a:\\")) || (path == wxT("b:\\")) )
                imageId = wxFileIconsTable::floppy;
            else
                imageId = wxFileIconsTable::removeable;
            break;
        case wxFS_VOL_DVDROM:
        case wxFS_VOL_CDROM:
            imageId = wxFileIconsTable::cdrom;
            break;
        case wxFS_VOL_NETWORK:
            if (path[0] == wxT('\\'))
                continue; // skip "\\computer\folder"
            imageId = wxFileIconsTable::drive;
            break;
        case wxFS_VOL_DISK:
        case wxFS_VOL_OTHER:
        default:
            imageId = wxFileIconsTable::drive;
            break;
        }
        paths.Add(path);
        names.Add(vol.GetDisplayName());
        icon_ids.Add(imageId);
    }
#elif defined(__OS2__)
    APIRET rc;
    ULONG ulDriveNum = 0;
    ULONG ulDriveMap = 0;
    rc = ::DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
    if ( rc == 0)
    {
        size_t i = 0;
        while (i < 26)
        {
            if (ulDriveMap & ( 1 << i ))
            {
                const wxString path = wxFileName::GetVolumeString(
                    'A' + i, wxPATH_GET_SEPARATOR);
                const wxString name = wxFileName::GetVolumeString(
                    'A' + i, wxPATH_NO_SEPARATOR);

                // Note: If _filesys is unsupported by some compilers,
                //       we can always replace it by DosQueryFSAttach
                char filesysname[20];
#ifdef __WATCOMC__
                ULONG cbBuffer = sizeof(filesysname);
                PFSQBUFFER2 pfsqBuffer = (PFSQBUFFER2)filesysname;
                APIRET rc = ::DosQueryFSAttach(name.fn_str(),0,FSAIL_QUERYNAME,pfsqBuffer,&cbBuffer);
                if (rc != NO_ERROR)
                {
                    filesysname[0] = '\0';
                }
#else
                _filesys(name.fn_str(), filesysname, sizeof(filesysname));
#endif
                /* FAT, LAN, HPFS, CDFS, NFS */
                int imageId;
                if (path == wxT("A:\\") || path == wxT("B:\\"))
                    imageId = wxFileIconsTable::floppy;
                else if (!strcmp(filesysname, "CDFS"))
                    imageId = wxFileIconsTable::cdrom;
                else if (!strcmp(filesysname, "LAN") ||
                    !strcmp(filesysname, "NFS"))
                    imageId = wxFileIconsTable::drive;
                else
                    imageId = wxFileIconsTable::drive;
                paths.Add(path);
                names.Add(name);
                icon_ids.Add(imageId);
            }
            i ++;
        }
    }
#else // !__WIN32__, !__OS2__
    /* If we can switch to the drive, it exists. */
    for ( char drive = 'A'; drive <= 'Z'; drive++ )
    {
        const wxString
            path = wxFileName::GetVolumeString(drive, wxPATH_GET_SEPARATOR);

        if (wxIsDriveAvailable(path))
        {
            paths.Add(path);
            names.Add(wxFileName::GetVolumeString(drive, wxPATH_NO_SEPARATOR));
            icon_ids.Add(drive <= 2 ? wxFileIconsTable::floppy
                : wxFileIconsTable::drive);
        }
    }
#endif // __WIN32__/!__WIN32__

#elif defined(__WXMAC__) && wxOSX_USE_COCOA_OR_CARBON

    ItemCount volumeIndex = 1;
    OSErr err = noErr ;

    while( noErr == err )
    {
        HFSUniStr255 volumeName ;
        FSRef fsRef ;
        FSVolumeInfo volumeInfo ;
        err = FSGetVolumeInfo(0, volumeIndex, NULL, kFSVolInfoFlags , &volumeInfo , &volumeName, &fsRef);
        if( noErr == err )
        {
            wxString path = wxMacFSRefToPath( &fsRef ) ;
            wxString name = wxMacHFSUniStrToString( &volumeName ) ;

            if ( (volumeInfo.flags & kFSVolFlagSoftwareLockedMask) || (volumeInfo.flags & kFSVolFlagHardwareLockedMask) )
            {
                icon_ids.Add(wxFileIconsTable::cdrom);
            }
            else
            {
                icon_ids.Add(wxFileIconsTable::drive);
            }
            // todo other removable

            paths.Add(path);
            names.Add(name);
            volumeIndex++ ;
        }
    }

#elif defined(__UNIX__) || defined(__WXPALMOS__)
    paths.Add(wxT("/"));
    names.Add(wxT("/"));
    icon_ids.Add(wxFileIconsTable::computer);
#else
#error "Unsupported platform in wxGenericDirCtrl!"
#endif
    wxASSERT_MSG( (paths.GetCount() == names.GetCount()), wxT("The number of paths and their human readable names should be equal in number."));
    wxASSERT_MSG( (paths.GetCount() == icon_ids.GetCount()), wxT("Wrong number of icons for available drives."));
    return paths.GetCount();
}

